﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XXF.BaseService.ServiceCenter.Client.RemoteClient;
using XXF.BaseService.ServiceCenter.SystemRuntime;
using XXF.Extensions;

namespace XXF.BaseService.ServiceCenter.Client.Sdk
{
    /// <summary>
    /// ThriftSdk提供类
    /// </summary>
    public class ThriftSDKProvider
    {
        private const string servicetemplate = @"
using System;
using System.Collections.Generic;
using System.Text;

namespace {$命名空间}
{
    /// <summary>
    /// {$服务注释}
    /// </summary>
    public class {$服务名}Client:{$服务远程客户端}
    {
        public {$服务名}Client()
        {
        }

        {$方法集合}
       
    }
}
";
        private const string methodtemplate = @"
        /// <summary>
        /// {$方法注释}
        /// </summary>
       {$方法参数注释}    
        public {$方法返回值} {$方法名}({$参数集合})
        {
            return Call<{$方法返回值2}>(""{$方法名}"",new object[]{{$参数集合2}}); 
        }
";         
        private const string voidmethodtemplate = @"
        /// <summary>
        /// {$方法注释}
        /// </summary>
       {$方法参数注释}    
        public {$方法返回值} {$方法名}({$参数集合})
        {
            Call<bool>(""{$方法名}"",new object[]{{$参数集合2}}); 
        }
";        
        
        private const string methodparamstemplate = @"{$参数类型} {$参数名},";
        private const string methodparamstemplate2 = @"{$参数名},";
        private const string mehtodparamremarktemplate = @"/// <param name=""{$参数名}"">{$参数注释}</param>";

        private const string classtemplate = @"
using System;
using System.Collections.Generic;
using System.Text;

namespace {$命名空间}
{
    /// <summary>
    /// {$类注释}
    /// </summary> 
    public class {$类名} 
    {
        {$属性集合}
    }
}";
        private const string propertytemplate = @"
        /// <summary>
        /// {$属性注释}
        /// </summary>     
        public {$属性类型} {$属性名} {get;set;}
";
        /// <summary>
        /// 将Thrift协议转成本地代码
        /// </summary>
        /// <param name="servicenamespace"></param>
        /// <param name="tofiledir"></param>
        public void ToLocalFile(string servicenamespace, string tofiledir)
        {
            try
            {
                tofiledir = tofiledir.TrimEnd('/') + "/";
                XXF.Common.IOHelper.CreateDirectory(tofiledir);
                var clientprovider = new Provider.ClientProviderPool().Get(servicenamespace);
                var protocal = clientprovider.GetServiceProtocal(); string ServiceNameSpace = clientprovider.GetServiceNameSpace();
                /*生成服务*/
                var servicecode = GetServiceCode(servicenamespace, tofiledir);
                System.IO.File.WriteAllText(tofiledir + protocal.Name + ".cs", servicecode);
                /*生成实体*/
                foreach (var e in protocal.EntityProtocals)
                {
                    string classcontent = GetEntitiyCode(servicenamespace, tofiledir, e.Name);
                    System.IO.File.WriteAllText(tofiledir + e.Name + ".cs", classcontent);
                }
            }
            catch (Exception exp)
            {
                LogHelper.Error(-1, EnumLogType.Client, string.Format("将Thrift协议转成本地代码出错,服务命名空间:{0}",servicenamespace.NullToEmpty()), exp);
                throw exp;
            }

        }
        /// <summary>
        /// 获取服务生成代码
        /// </summary>
        /// <param name="servicenamespace"></param>
        /// <param name="tofiledir"></param>
        /// <returns></returns>
        private string GetServiceCode(string servicenamespace, string tofiledir)
        {
            tofiledir = tofiledir.TrimEnd('/') + "/";
            var clientprovider = new Provider.ClientProviderPool().Get(servicenamespace);
            var protocal = clientprovider.GetServiceProtocal(); string ServiceNameSpace = clientprovider.GetServiceNameSpace();
            /*生成服务文件*/
            string methodlist = "";
            foreach (var m in protocal.MethodProtocols)
            {
                string paramlist = ""; string paramlist2 = "";
                foreach (var p in m.InputParams)
                {
                    paramlist += methodparamstemplate.Replace("{$参数名}", p.Name).Replace("{$参数类型}", p.TypeName);
                    paramlist2 += methodparamstemplate2.Replace("{$参数名}", p.Name);
                }
                string mehtodparamremarktlist = "";
                foreach (var p in m.MethodDoc.InputParamsText)
                {
                    mehtodparamremarktlist += mehtodparamremarktemplate.Replace("{$参数名}",p.Key).Replace("{$参数注释}",p.Value);
                }
                string tmethodtemplate = methodtemplate; 
                if(m.ReturnParam.TypeName.ToLower() == "void")
                {
                    tmethodtemplate = voidmethodtemplate;
                }
                
                methodlist += tmethodtemplate.Replace("{$方法返回值}", m.ReturnParam.TypeName)
                        .Replace("{$方法返回值2}", (m.ReturnParam.TypeName.ToLower() == "void") ? "bool" : m.ReturnParam.TypeName)
                        .Replace("{$方法名}", m.Name)
                        .Replace("{$参数集合}", paramlist.TrimEnd(',')).Replace("{$参数集合2}", paramlist2.TrimEnd(','))
                        .Replace("{$方法注释}", string.Format("【方法】{0},【描述】{1}", m.MethodDoc.Text, m.MethodDoc.Description))
                        .Replace("{$方法参数注释}", mehtodparamremarktlist); ;

            }
            string code = servicetemplate.Replace("{$命名空间}", ServiceNameSpace)
                .Replace("{$服务远程客户端}", typeof(ThriftRemoteClient).FullName)
                .Replace("{$服务名}", protocal.Name)
                .Replace("{$服务注释}", string.Format("【服务】{0},【描述】{1}", protocal.ServiceDoc.Text, protocal.ServiceDoc.Description))
               .Replace("{$方法集合}", methodlist);
            return code;
        }
        /// <summary>
        /// 获取实体生成代码
        /// </summary>
        /// <param name="servicenamespace"></param>
        /// <param name="tofiledir"></param>
        /// <param name="entityname"></param>
        /// <returns></returns>
        private string GetEntitiyCode(string servicenamespace, string tofiledir, string entityname)
        {
            tofiledir = tofiledir.TrimEnd('/') + "/";
            var clientprovider = new Provider.ClientProviderPool().Get(servicenamespace);
            var protocal = clientprovider.GetServiceProtocal(); string ServiceNameSpace = clientprovider.GetServiceNameSpace();

            string classlist = "";
            foreach (var e in protocal.EntityProtocals)
            {
                if (e.Name != entityname)
                    continue;
                string propertylist = "";
                for (int i = 0; i < e.PropertyParams.Count; i++)
                {
                    var pty = e.PropertyParams[i];
                    var doc = e.PropertyDocs[i];
                    propertylist += propertytemplate.Replace("{$属性类型}", pty.TypeName)
                        .Replace("{$属性名}", pty.Name)
                        .Replace("{$属性注释}", string.Format("【属性】{0},【描述】{1}", doc.Text, doc.Description));
                }
                string classcontent = classtemplate.Replace("{$类名}", e.Name)
                     .Replace("{$命名空间}", ServiceNameSpace)
                     .Replace("{$属性集合}", propertylist)
                     .Replace("{$类注释}", string.Format("【类】{0},【描述】{1}", e.EntityDoc.Text, e.EntityDoc.Description));
                classlist += classcontent;
            }
            return classlist;
        }
    }
}
